

package top.continew.admin.rpc;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.shengchao.examstar.rpc.question.api.IErrorQuestionRpc;
import com.shengchao.examstar.rpc.question.req.ErrorQuestionReq;
import com.shengchao.examstar.rpc.question.resp.ErrorQuestionInfoResp;
import com.shengchao.examstar.rpc.question.resp.ErrorQuestionStatistics;
import com.shengchao.examstar.rpc.question.resp.QuestionListResp;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.question.model.question.QuestionExt;
import top.continew.admin.question.model.question.QuestionSetQuestion;
import top.continew.admin.question.model.question.UserDoQuestion;
import top.continew.admin.question.user.service.IQuestionService;
import top.continew.admin.question.user.service.IUserQuestionService;
import top.continew.admin.question.user.service.question.entity.AbstractQuestion;
import top.continew.admin.question.user.service.questionset.entity.AbstractQuestionSet;
import top.continew.admin.question.user.service.questionset.entity.WrongQuestionSet;
import top.continew.admin.question.user.service.questionset.enums.QuestionSetTypeEnum;
import top.continew.admin.question.user.service.questionset.factory.QuestionSetFactory;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static top.continew.admin.rpc.QuestionRpc.getQuestionListResp;

@DubboService
public class ErrorQuestionRpc implements IErrorQuestionRpc {

    @Autowired
    private IUserQuestionService iUserQuestionService;

    @Autowired
    private IQuestionService iQuestionService;

    @Override
    public ErrorQuestionStatistics getErrorQuestionStatistics(Long specificationType) {
        ErrorQuestionStatistics errorQuestionStatistics = new ErrorQuestionStatistics();
        Long userLoginId = UserContextHolder.getUserId();
        //获取错题题集
        WrongQuestionSet wrongQuestionSet = (WrongQuestionSet)QuestionSetFactory
            .of(userLoginId, QuestionSetTypeEnum.WRONG_QUESTION.getCode());
        Executor executor = Executors.newVirtualThreadPerTaskExecutor();
        //        CompletableFuture<List<UserDoQuestion>> userDoQuestionsFuture = CompletableFuture
        //                .supplyAsync(() -> iUserQuestionService.getAllListByUserId(userLoginId, String.valueOf(wrongQuestionSet
        //                        .getQuestionSet()
        //                        .getId()), specificationType), executor);
        //题集题数
        long sum = wrongQuestionSet.getQuestionCount(specificationType);
        errorQuestionStatistics.setQuestionSum(sum);
        errorQuestionStatistics.setTrueQuestionSum(0L);
        //获取正确题数
        long trueSum = wrongQuestionSet.getQuestionCount(specificationType, 1);
        errorQuestionStatistics.setTrueQuestionSum(trueSum);
        return errorQuestionStatistics;
    }

    @Override
    public List<ErrorQuestionInfoResp> getErrorQuestionList(ErrorQuestionReq errorQuestionReq) throws ExecutionException, InterruptedException {
        Long userLoginId = UserContextHolder.getUserId();
        //获取错题题集
        AbstractQuestionSet abstractQuestionSet = QuestionSetFactory.of(userLoginId, QuestionSetTypeEnum.WRONG_QUESTION
            .getCode());
        if (abstractQuestionSet == null) {
            return List.of();
        }
        Executor executor = Executors.newVirtualThreadPerTaskExecutor();
        CompletableFuture<List<UserDoQuestion>> userDoQuestionsFuture = CompletableFuture
            .supplyAsync(() -> iUserQuestionService.getAllListByUserId(userLoginId, String.valueOf(abstractQuestionSet
                .getQuestionSet()
                .getId()), errorQuestionReq.getSpecificationType()), executor);
        //获取错题列表
        List<QuestionSetQuestion> questionSetQuestions = abstractQuestionSet.getQuestionList()
            .stream()
            .filter(questionSetQuestion -> {
                if (errorQuestionReq.getIsMaster()) {
                    return questionSetQuestion.getStatus() == 1;
                } else {
                    return questionSetQuestion.getStatus() == 0;
                }
            })
            .toList();
        if (questionSetQuestions.isEmpty()) {
            return List.of();
        }
        Map<Long, List<QuestionSetQuestion>> qsq = questionSetQuestions.stream()
            .collect(Collectors.groupingBy(QuestionSetQuestion::getQuestionId));
        if (qsq.isEmpty()) {
            return List.of();
        }
        //获取题目信息
        List<AbstractQuestion> questionList = iQuestionService.getQuestionList(questionSetQuestions.stream()
            .map(QuestionSetQuestion::getQuestionId)
            .toList());
        if (questionList.isEmpty()) {
            return List.of();
        }
        List<ErrorQuestionInfoResp> errorQuestionInfoResps = new ArrayList<>(questionList.size());
        //组装题目
        for (AbstractQuestion questionListResp : questionList) {
            List<QuestionListResp> questionListResps = getQuestionListResp(questionListResp, Map.of());
            for (QuestionListResp listResp : questionListResps) {
                ErrorQuestionInfoResp errorQuestionInfoResp = new ErrorQuestionInfoResp();
                errorQuestionInfoResp.setQuestionId(listResp.getId());
                errorQuestionInfoResp.setQuestionSetId(abstractQuestionSet.getQuestionSet().getId());
                errorQuestionInfoResp.setMaterial(listResp.getMaterial());
                errorQuestionInfoResp.setTitle(listResp.getTitle());
                errorQuestionInfoResp.setAnswer(questionListResp.getAnswer());
                errorQuestionInfoResp.setSelect(listResp.getSelect());
                errorQuestionInfoResp.setType(listResp.getType());
                errorQuestionInfoResp.setTypeName(listResp.getTypeName());
                errorQuestionInfoResp.setBlankSum(listResp.getBlankSum());
                errorQuestionInfoResp.setLineOptions(listResp.getLineOptions());
                errorQuestionInfoResp.setSpecificationType(listResp.getSpecificationType());
                errorQuestionInfoResps.add(errorQuestionInfoResp);
            }
        }
        List<UserDoQuestion> userDoQuestions = userDoQuestionsFuture.get();
        //做题记录
        Map<Long, List<UserDoQuestion>> map = userDoQuestions.stream()
            .collect(Collectors.groupingBy(UserDoQuestion::getQuestionId));
        for (ErrorQuestionInfoResp errorQuestionInfoResp : errorQuestionInfoResps) {
            if (qsq.containsKey(errorQuestionInfoResp.getQuestionId())) {
                List<QuestionSetQuestion> questionSetQuestionList = qsq.get(errorQuestionInfoResp.getQuestionId());
                //按时间倒序
                questionSetQuestionList.sort(Comparator.comparing(QuestionSetQuestion::getCtime).reversed());
                //错题数量
                errorQuestionInfoResp.setErrorSum((long)questionSetQuestionList.size());
                errorQuestionInfoResp.setIsImportant(questionSetQuestionList.getFirst().getIsImportant());
                if (errorQuestionInfoResp.getIsImportant() == null) {
                    errorQuestionInfoResp.setIsImportant(2L);
                }
                //最后一次做题答案
                QuestionExt questionExt = JSON.parseObject(questionSetQuestionList.getFirst()
                    .getExt(), QuestionExt.class);
                //最后一次做题时间
                Date last = new Date(questionSetQuestionList.getFirst().getUtime());
                errorQuestionInfoResp.setUserAnswer(questionExt.getUserAnswer());
                //第一次做错时间
                errorQuestionInfoResp.setCreateTime(new Date(questionSetQuestionList.getLast().getCtime()));
                errorQuestionInfoResp.setSource(questionExt.getFromName());
                List<UserDoQuestion> questions = map.get(errorQuestionInfoResp.getQuestionId());
                if (questions != null && !questions.isEmpty()) {
                    questions.sort(Comparator.comparing(UserDoQuestion::getCreateTime).reversed());
                    UserDoQuestion userDoQuestion = questions.getFirst();
                    if (userDoQuestion.getCreateTime().after(last)) {
                        errorQuestionInfoResp.setUserAnswer(userDoQuestion.getUserAnswer());
                    }
                } else {
                    errorQuestionInfoResp.setIsMaster(false);
                }
            }
        }
        return errorQuestionInfoResps.stream()
            .filter(errorQuestionInfoResp -> filterQuestion(errorQuestionReq, errorQuestionInfoResp))
            .toList();
    }

    @Override
    public void markTheHighlights(Long questionId, Long isImportant) {
        Long userId = UserContextHolder.getUserId();
        iQuestionService.markTheHighlights(questionId, userId, isImportant);
    }

    private boolean filterQuestion(ErrorQuestionReq errorQuestionReq, ErrorQuestionInfoResp errorQuestionInfoResp) {
        if (StrUtil.isNotBlank(errorQuestionReq.getStartTime()) && StrUtil.isNotBlank(errorQuestionReq.getEndTime())) {
            Date startTime = DateUtil.parse(errorQuestionReq.getStartTime());
            Date endTime = DateUtil.parse(errorQuestionReq.getEndTime());
            if (errorQuestionInfoResp.getCreateTime().before(startTime) || errorQuestionInfoResp.getCreateTime()
                .after(endTime)) {
                return false;
            }
        }
        if (errorQuestionReq.getSpecificationType() != null) {
            if (!Objects.equals(errorQuestionReq.getSpecificationType(), errorQuestionInfoResp
                .getSpecificationType())) {
                return false;
            }
        }
        if (StrUtil.isNotBlank(errorQuestionReq.getSearchName())) {
            return errorQuestionInfoResp.getTitle().contains(errorQuestionReq.getSearchName());
        }
        return true;
    }
}
